﻿using CommunityToolkit.Mvvm.Messaging;
using Dark_Core_Server.Models.Article;
using Dark_Core_Server.Models.Universal;
using Dark_Core_Server.Models.User;
using DarkSKL_Core.ArgModules;
using DarkSKL_Core.ConfigModules;
using DarkSKL_Core.MongoDBModules.Helper;
using DarkSKL_Core.MongoDBModules.Models;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;
using MongoDB.Driver;
using Serilog;

namespace Dark_Core_Server.Service
{
    /// <summary>
    /// 文章服务
    /// <remarks>
    /// 文章删除完成后，会基于 <see cref="WeakReferenceMessenger"/> 发送一条 ArticleDeleted 消息，
    /// 消息参数类型为 <see cref="ArticleDocument"/>。
    /// </remarks>
    /// </summary>
    public class ArticleService
    {
        /// <summary>文章集合</summary>
        public IMongoCollection<ArticleDocument> ArticleCollection;

        /// <summary>评论集合</summary>
        public IMongoCollection<CommentDocument> CommentCollection;

        /// <summary>
        /// 构造函数，初始化MongoDB相关配置与集合引用。
        /// </summary>
        public ArticleService()
        {
            // 读取数据库配置
            DatabaseConfig config = new DatabaseConfig()
            {
                DatabaseName = EnvironmentConfigController
                    .ConfigController
                    .GetConfig<string>("DB:ARTICLE_DB_NAME"),
                User = EnvironmentConfigController.ConfigController.GetConfig<string>("DB:USER"),
                Password = EnvironmentConfigController
                    .ConfigController
                    .GetConfig<string>("DB:PASS"),
                Host = EnvironmentConfigController.ConfigController.GetConfig<string>("DB:HOST"),
                Port = EnvironmentConfigController.ConfigController.GetConfig<int>("DB:PORT"),
                Args = EnvironmentConfigController.ConfigController.GetConfig<string>("DB:ARGS")
            };

            // 文章集合 (名称来自配置或使用 "basicUnit" 作为默认)
            ArticleCollection = MongodbBuilder.CreateCollection<ArticleDocument>(
                config,
                EnvironmentConfigController
                    .ConfigController
                    .GetConfig<string>("DB:ARTICLE_DB_COLLECTION") ?? "basicUnit"
            );

            // 评论集合 (示例名称为 "Comment"，可根据项目需要修改)
            CommentCollection = MongodbBuilder.CreateCollection<CommentDocument>(
                config,
                EnvironmentConfigController
                    .ConfigController
                    .GetConfig<string>("DB:ARTICLE_DB_COMMENT_COLLECTION") ?? "commentUnit"
            );

            // 用户删除时，自动删除其发布的文章
            WeakReferenceMessenger
                .Default
                .Register<UserDocument, string>(
                    this,
                    "UserDeleted",
                    async (recipient, message) =>
                    {
                        var queryResult = await QueryArticleListAsync(
                            ArticleQueryMode.AuthorID,
                            new[] { message.id.ToString() }
                        );
                        queryResult
                            .Data
                            .Rows
                            .ForEach(async x =>
                            {
                                await DeleteArticleAsync(message.id, x.id);
                            });
                    }
                );
        }

        #region Article - Create

        /// <summary>
        /// 创建文章
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="simpleArticleRecord">文章记录</param>
        /// <returns></returns>
        public async Task<ResponseMsg<bool>> CreateArticle(
            ObjectId userId,
            SimpleArticleRecord simpleArticleRecord
        )
        {
            try
            {
                // 将简单记录转换为 ArticleDocument，其中 id 和 CreateTime 由 DocumentUnit 基类自动生成
                var articleDocument = simpleArticleRecord.ToDocument(userId);

                await ArticleCollection.InsertOneAsync(articleDocument);
                return true.CreateResponseMsg("创建成功", UniversalState.Success);
            }
            catch (Exception e)
            {
                Log.Error($"ArticleService.CreateArticle Exception :{e.Message}");
                return false.CreateResponseMsg(
                    $"ArticleService.CreateArticle Exception :{e.Message}",
                    UniversalState.Error
                );
            }
        }

        #endregion

        #region Article - Delete

        /// <summary>
        /// 删除文章
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="articleId">文章ID</param>
        /// <returns></returns>
        public async Task<ResponseMsg<bool>> DeleteArticleAsync(ObjectId userId, ObjectId articleId)
        {
            try
            {
                var findResult = await QueryArticleListAsync(
                    ArticleQueryMode.ArticleID,
                    new[] { articleId.ToString() }
                );
                if (findResult.Data.Total < 1)
                    throw new Exception("No documents were found");

                // 删除文章
                var deleteResult = await ArticleCollection.DeleteOneAsync(
                    x => x.UserId == userId && x.id == articleId
                );
                if (deleteResult.DeletedCount < 1)
                    throw new Exception("No documents were deleted");

                // 文章删除后，发送通知
                WeakReferenceMessenger.Default.Send(findResult.Data.Rows[0], "ArticleDeleted");
                // 删除所有评论
                await CommentCollection.DeleteManyAsync(x => x.ArticleId == articleId);

                return true.CreateResponseMsg("删除成功", UniversalState.Success);
            }
            catch (Exception e)
            {
                Log.Error($"ArticleService.DeleteArticleAsync Exception :{e.Message}");
                return false.CreateResponseMsg(
                    $"ArticleService.DeleteArticleAsync Exception :{e.Message}",
                    UniversalState.Error
                );
            }
        }

        #endregion

        #region Article - Query


        /// <summary>
        /// 查询文章列表
        /// </summary>
        /// <param name="queryMode">查询模式</param>
        /// <param name="args">查询参数</param>
        /// <param name="isSortByTime">是否排序</param>
        /// <param name="pageNum">分页数</param>
        /// <param name="pageSize">分页大小</param>
        /// <returns>该值中 Data 字段为 DataArrResponse，其 Data 字段为 List</returns>
        public async Task<
            ResponseMsg<DataArrResponse<ArticleDocument>>
        > QueryArticleListAsync(
            ArticleQueryMode queryMode,
            string[] args,
            bool isSortByTime = false,
            int pageNum = 0,
            int pageSize = 999
        )
        {
            try
            {
                var findOption = new FindOptions<ArticleDocument>
                {
                    Sort = isSortByTime
                        ? Builders<ArticleDocument>.Sort.Descending(x => x.CreateTime)
                        : Builders<ArticleDocument>.Sort.Ascending(x => x.CreateTime),
                    Skip = pageNum * pageSize,
                    Limit = pageSize,
                    Projection = Builders<ArticleDocument>
                        .Projection
                        .Exclude(x => x.Content)
                        .Exclude(x => x.FileIds)
                };

                // 构造过滤器
                var findFilter = queryMode switch
                {
                    ArticleQueryMode.All => Builders<ArticleDocument>.Filter.Empty,

                    ArticleQueryMode.AuthorID
                        => Builders<ArticleDocument>
                            .Filter
                            .Eq(x => x.UserId, ObjectId.Parse(args[0])),

                    ArticleQueryMode.ArticleID
                        => Builders<ArticleDocument>.Filter.Eq(x => x.id, ObjectId.Parse(args[0])),

                    ArticleQueryMode.Tag
                        => Builders<ArticleDocument>.Filter.AnyEq(x => x.Tags, args[0]),

                    ArticleQueryMode.ExactTitle
                        => Builders<ArticleDocument>.Filter.Eq(x => x.Title, args[0]),

                    ArticleQueryMode.FuzzyTitle
                        => Builders<ArticleDocument>
                            .Filter
                            .Regex(x => x.Title, new BsonRegularExpression(args[0], "i")),
                    ArticleQueryMode.AuthorIdAndFuzzyTitle
                        => Builders<ArticleDocument>
                            .Filter
                            .And(
                                Builders<ArticleDocument>
                                    .Filter
                                    .Eq(x => x.UserId, ObjectId.Parse(args[0])),
                                Builders<ArticleDocument>
                                    .Filter
                                    .Regex(x => x.Title, new BsonRegularExpression(args[1], "i"))
                            ),
                    ArticleQueryMode.AuthorIdAndTag
                        => Builders<ArticleDocument>
                            .Filter
                            .And(
                                Builders<ArticleDocument>
                                    .Filter
                                    .Eq(x => x.UserId, ObjectId.Parse(args[0])),
                                Builders<ArticleDocument>.Filter.AnyEq(x => x.Tags, args[1])
                            ),
                    _ => throw new Exception("Invalid query mode")
                };

                var findResult = await ArticleCollection.FindAsync(findFilter, findOption);
                var articles = await findResult.ToListAsync();
                var findCount = await ArticleCollection.CountDocumentsAsync(findFilter);

                return articles
                    .ToDataArrResponse(findCount)
                    .CreateResponseMsg("查询成功", UniversalState.Success);
            }
            catch (Exception e)
            {
                Log.Error($"ArticleService QueryArticleAsync Exception :{e.Message}");
                return new List<ArticleDocument>()
                    .ToDataArrResponse(0)
                    .CreateResponseMsg(
                        $"ArticleService QueryArticleAsync Exception :{e.Message}",
                        UniversalState.Error
                    );
            }
        }

        ///
        public async Task<ResponseMsg<ArticleDocument>> QueryArticleContentAsync(string id)
        {
            try
            {
                if(!ObjectId.TryParse(id,out ObjectId articleId)) throw new Exception("Invalid article id");

                var findResult = await ArticleCollection.FindOneAndUpdateAsync(
                    x => x.id == articleId,
                    Builders<ArticleDocument>.Update.Inc(x => x.ReadCount, 1),
                    new FindOneAndUpdateOptions<ArticleDocument>()
                    {
                        ReturnDocument = ReturnDocument.After
                    }
                );
                if (findResult == null)
                    throw new Exception("No documents were found");
                return findResult.CreateResponseMsg("查询成功", UniversalState.Success);
            }
            catch (Exception e)
            {
                Log.Error($"ArticleService QueryArticleContentAsync Exception :{e.Message}");
                return ArticleDocument
                    .Empty
                    .CreateResponseMsg(
                        $"ArticleService QueryArticleContentAsync Exception :{e.Message}",
                        UniversalState.Error
                    );
            }
        }

        #endregion

        #region Article - Update

        /// <summary>
        /// 刷新文章
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="articleId">文章ID</param>
        /// <param name="record">记录</param>
        /// <returns></returns>
        public async Task<ResponseMsg<bool>> UpdateArticleAsync(
            ObjectId userId,
            ObjectId articleId,
            ModifyArticleRecord record
        )
        {
            try
            {
                bool isExists =
                    (
                        await QueryArticleListAsync(
                            ArticleQueryMode.ArticleID,
                            new[] { articleId.ToString() }
                        )
                    )
                        .Data
                        .Total > 0;

                if (!isExists)
                    throw new Exception("The article does not exist.");

                // 拼接更新语句
                UpdateDefinition<ArticleDocument> updateDefinition = Builders<ArticleDocument>
                    .Update
                    .Combine();

                if (record.Title is not null)
                    updateDefinition = updateDefinition.Set(x => x.Title, record.Title);
                if (record.Content is not null)
                    updateDefinition = updateDefinition.Set(x => x.Content, record.Content);
                if (record.Synopsis is not null)
                    updateDefinition = updateDefinition.Set(x => x.Synopsis, record.Synopsis);
                if (record.PictureUrl is not null)
                    updateDefinition = updateDefinition.Set(x => x.PictureUrl, record.PictureUrl);
                if (record.Tags is not null)
                    updateDefinition = updateDefinition.Set(x => x.Tags, record.Tags);
                if (record.ViewLevel is not null)
                    updateDefinition = updateDefinition.Set(x => x.ViewLevel, record.ViewLevel);
                if (record.FileIds is not null)
                {
                    await Console.Out.WriteLineAsync("写入FileIds");
                    updateDefinition = updateDefinition.Set(
                        x => x.FileIds,
                        record.FileIds.Select(ObjectId.Parse)
                    );
                }

                // 执行更新
                var updateResult = await ArticleCollection.FindOneAndUpdateAsync(
                    x => x.UserId == userId && x.id == articleId,
                    updateDefinition
                );

                if (updateResult is null)
                    throw new Exception("No documents were updated");

                return true.CreateResponseMsg("更新成功", UniversalState.Success);
            }
            catch (Exception e)
            {
                Log.Error($"ArticleService UpdateArticleAsync Exception :{e.Message}");
                return false.CreateResponseMsg(
                    $"ArticleService UpdateArticleAsync Exception :{e.Message}",
                    UniversalState.Error
                );
            }
        }

        #endregion

        #region Comment Logic (Integrated Here)

        /// <summary>
        /// 创建评论
        /// </summary>
        /// <param name="userId">评论用户ID</param>
        /// <param name="articleId">目标文章ID</param>
        /// <param name="content">评论内容</param>
        /// <returns>是否创建成功</returns>
        public async Task<ResponseMsg<bool>> CreateCommentAsync(
            ObjectId userId,
            ObjectId articleId,
            string content
        )
        {
            try
            {
                // 可以先判断文章是否存在
                bool articleExists =
                    (
                        await QueryArticleListAsync(
                            ArticleQueryMode.ArticleID,
                            new[] { articleId.ToString() }
                        )
                    )
                        .Data
                        .Total > 0;

                if (!articleExists)
                    throw new Exception("Article does not exist.");

                // 由于 CommentDocument 继承自 DocumentUnit，id 与 CreateTime 会在构造函数中自动设置
                var commentDoc = new CommentDocument
                {
                    ArticleId = articleId,
                    UserId = userId,
                    Content = content
                };

                await CommentCollection.InsertOneAsync(commentDoc);
                return true.CreateResponseMsg("创建评论成功", UniversalState.Success);
            }
            catch (Exception e)
            {
                Log.Error($"ArticleService.CreateCommentAsync Exception :{e.Message}");
                return false.CreateResponseMsg(
                    $"ArticleService.CreateCommentAsync Exception :{e.Message}",
                    UniversalState.Error
                );
            }
        }

        /// <summary>
        /// 删除评论
        /// </summary>
        /// <param name="commentId">评论ID</param>
        /// <param name="userId">当前操作用户ID，可用于验证是否本人</param>
        /// <returns></returns>
        public async Task<ResponseMsg<bool>> DeleteCommentAsync(ObjectId commentId, ObjectId userId)
        {
            try
            {
                // 如果需验证归属权，可在 filter 中加 x.UserId == userId
                var filter = Builders<CommentDocument>.Filter.Eq(x => x.id, commentId);
                var deleteResult = await CommentCollection.DeleteOneAsync(filter);

                if (deleteResult.DeletedCount < 1)
                    throw new Exception("No comments were deleted");

                return true.CreateResponseMsg("删除评论成功", UniversalState.Success);
            }
            catch (Exception e)
            {
                Log.Error($"ArticleService.DeleteCommentAsync Exception :{e.Message}");
                return false.CreateResponseMsg(
                    $"ArticleService.DeleteCommentAsync Exception :{e.Message}",
                    UniversalState.Error
                );
            }
        }

        /// <summary>
        /// 更新评论内容
        /// </summary>
        /// <param name="commentId">评论ID</param>
        /// <param name="userId">用户ID（可用于判断是否本人）</param>
        /// <param name="newContent">新的评论内容</param>
        /// <returns></returns>
        public async Task<ResponseMsg<bool>> UpdateCommentAsync(
            ObjectId commentId,
            ObjectId userId,
            string newContent
        )
        {
            try
            {
                // 如果需要同时验证用户ID，可在 Filter 中增加 x.UserId == userId
                var filter = Builders<CommentDocument>.Filter.Eq(x => x.id, commentId);
                var update = Builders<CommentDocument>.Update.Set(x => x.Content, newContent);

                var result = await CommentCollection.UpdateOneAsync(filter, update);

                if (result.ModifiedCount < 1)
                    throw new Exception("No comments were updated");

                return true.CreateResponseMsg("更新评论成功", UniversalState.Success);
            }
            catch (Exception e)
            {
                Log.Error($"ArticleService.UpdateCommentAsync Exception :{e.Message}");
                return false.CreateResponseMsg(
                    $"ArticleService.UpdateCommentAsync Exception :{e.Message}",
                    UniversalState.Error
                );
            }
        }

        /// <summary>
        /// 查询评论
        /// </summary>
        /// <param name="mode">查询模式</param>
        /// <param name="arg">查询参数</param>
        /// <param name="pageNum">分页序号</param>
        /// <param name="pageSize">分页大小</param>
        /// <returns></returns>
        public async Task<ResponseMsg<DataArrResponse<CommentDocument>>> QueryCommentAsync(
            CommentQueryMode mode,
            string arg,
            int pageNum = 0,
            int pageSize = 999999
        )
        {
            try
            {
                var findOption = new FindOptions<CommentDocument>()
                {
                    Skip = pageNum * pageSize,
                    Limit = pageSize
                };

                // 根据模式构造过滤器
                var findFilter = mode switch
                {
                    CommentQueryMode.CommentID
                        => Builders<CommentDocument>.Filter.Eq(x => x.id, ObjectId.Parse(arg)),

                    CommentQueryMode.ArticleID
                        => Builders<CommentDocument>
                            .Filter
                            .Eq(x => x.ArticleId, ObjectId.Parse(arg)),

                    CommentQueryMode.UserID
                        => Builders<CommentDocument>.Filter.Eq(x => x.UserId, ObjectId.Parse(arg)),
                    _ => throw new Exception("Invalid comment query mode")
                };

                var findResult = await CommentCollection.FindAsync(findFilter, findOption);
                var commentList = await findResult.ToListAsync();
                var totalCount = await CommentCollection.CountDocumentsAsync(findFilter);

                return commentList
                    .ToDataArrResponse(totalCount)
                    .CreateResponseMsg("查询成功", UniversalState.Success);
            }
            catch (Exception e)
            {
                Log.Error($"ArticleService.QueryCommentAsync Exception :{e.Message}");
                return new List<CommentDocument>()
                    .ToDataArrResponse(0)
                    .CreateResponseMsg(
                        $"ArticleService.QueryCommentAsync Exception :{e.Message}",
                        UniversalState.Error
                    );
            }
        }

        #endregion
    }
}
